﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QUrl>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->init();
    this->initAudio();

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::openFile()
{
    //设置保存文件
    QString path=QDir::homePath();//获取系统当前目录
    QString title="选择输出文件"; //对话框标题
    QString filter="wav文件(*.wav)"; //文件过滤器
    QString selectedFile=QFileDialog::getSaveFileName(this,title,path,filter);

    if (!selectedFile.isEmpty()){
        ui->lineEdit_outputFile->setText(selectedFile);
    }
}

void MainWindow::onAudioBufferProbed(const QAudioBuffer& buffer)
{
    //处理探测到的缓冲区
    ui->spinBox_byteCount->setValue(buffer.byteCount());//缓冲区字节数
    ui->spinBox_duration->setValue(int(buffer.duration()/1000));//缓冲区时长
    ui->spinBox_frameCount->setValue(buffer.frameCount());//缓冲区帧数
    ui->spinBox_sampleCount->setValue(buffer.sampleCount());//缓冲区采样数

    QAudioFormat audioFormat=buffer.format();//缓冲区格式
    ui->spinBox_channelCount->setValue(audioFormat.channelCount()); //通道数
    ui->spinBox_sampleSize->setValue(audioFormat.sampleSize());//采样大小
    ui->spinBox_sampleRate->setValue(audioFormat.sampleRate());//采样率
    ui->spinBox_bytesPerFrame->setValue(audioFormat.bytesPerFrame());//每帧字节数

    if (audioFormat.byteOrder()==QAudioFormat::LittleEndian)
        ui->lineEdit_ByteOdrer->setText("LittleEndian");//字节序
    else
        ui->lineEdit_ByteOdrer->setText("BigEndian");

    ui->lineEdit_Codec->setText(audioFormat.codec());//编码格式

    if (audioFormat.sampleType()==QAudioFormat::SignedInt)//采样点类型
        ui->lineEdit_sampleType->setText("SignedInt");
    else if(audioFormat.sampleType()==QAudioFormat::UnSignedInt)
        ui->lineEdit_sampleType->setText("UnSignedInt");
    else if(audioFormat.sampleType()==QAudioFormat::Float)
        ui->lineEdit_sampleType->setText("Float");
    else
        ui->lineEdit_sampleType->setText("Unknown");

}

void MainWindow::onStateChanged(QMediaRecorder::State state)
{
    //录音状态变化
    ui->actionRecord->setEnabled(state!=QMediaRecorder::RecordingState);
    ui->actionPause->setEnabled(state==QMediaRecorder::RecordingState);
    ui->actionStop->setEnabled(state==QMediaRecorder::RecordingState);

    ui->pushButton_file->setEnabled(state==QMediaRecorder::StoppedState);
    ui->pushButton_file->setEnabled(state==QMediaRecorder::StoppedState);
}

void MainWindow::onDurationChanged(qint64 duration)
{
     ui->label_passtime->setText(QString("已录制 %1 秒").arg(duration / 1000));
}

void MainWindow::init()
{
    //channels 通道
    ui->comboChannels->addItem("1");
    ui->comboChannels->addItem("2");
    ui->comboChannels->addItem("4");

    //quality 质量
    ui->sliderQuality->setRange(0, int(QMultimedia::VeryHighQuality));
    ui->sliderQuality->setValue(int(QMultimedia::NormalQuality));

    //bitrates: 比特率
    ui->comboBitrate->addItem("32000");
    ui->comboBitrate->addItem("64000");
    ui->comboBitrate->addItem("96000");
    ui->comboBitrate->addItem("128000");
}

void MainWindow::initAudio()
{
    recorder = new QAudioRecorder(this);

    probe = new QAudioProbe();
    probe->setSource(recorder);

    //探测器
    connect(this->probe,SIGNAL(audioBufferProbed(QAudioBuffer)),
            this,SLOT(onAudioBufferProbed(QAudioBuffer)));


    //状态修改
    connect(recorder,SIGNAL(stateChanged(QMediaRecorder::State)),
            this,SLOT(onStateChanged(QMediaRecorder::State)));

    //录音持续时间变化
    connect(recorder, SIGNAL(durationChanged(qint64)),
            this,SLOT(onDurationChanged(qint64)));

    if (recorder->defaultAudioInput().isEmpty()){
        return;  //无音频录入设备
    }

    //添加音频设备
    for(const auto& device:recorder->audioInputs()){
         ui->comboDevices->addItem(device);
    }
    //支持的音频编码
    for(const auto& codec: recorder->supportedAudioCodecs()){
        ui->comboCodec->addItem(codec);
    }

    //支持的采样率
    for(auto rate:recorder->supportedAudioSampleRates()){
     ui->comboSampleRate->addItem(QString::number(rate));
    }
}


void MainWindow::on_actionRecord_triggered()
{
    //开始录音
    if (recorder->state() == QMediaRecorder::StoppedState) //已停止，重新设置
    {
        QString selectedFile=this->ui->lineEdit_outputFile->text().trimmed();
        if (selectedFile.isEmpty())
        {
            this->openFile();
            selectedFile=this->ui->lineEdit_outputFile->text().trimmed();
        }
        if (QFile::exists(selectedFile))
            if (!QFile::remove(selectedFile))
            {
                QMessageBox::critical(this,"错误","所设置录音输出文件被占用，无法删除");
                return;
            }
        recorder->setOutputLocation(QUrl::fromLocalFile(selectedFile));//设置输出文件

        recorder->setAudioInput(ui->comboDevices->currentText()); //设置录入设备

        //音频编码设置
        QAudioEncoderSettings settings;
        settings.setCodec(ui->comboCodec->currentText());//编码
        settings.setSampleRate(ui->comboSampleRate->currentText().toInt());//采样率
        settings.setBitRate(ui->comboBitrate->currentText().toInt());//比特率
        settings.setChannelCount(ui->comboChannels->currentText().toInt()); //通道数
        settings.setQuality(QMultimedia::EncodingQuality(ui->sliderQuality->value()));//品质
        if (ui->radioQuality->isChecked())//编码模式为固定品质,自动决定采样率，采样点大小
            settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);
        else
            settings.setEncodingMode(QMultimedia::ConstantBitRateEncoding);//固定比特率

        recorder->setAudioSettings(settings); //音频设置
    }
    recorder->record();
}

void MainWindow::on_pushButton_clicked()
{
    this->openFile();
}

void MainWindow::on_actionStop_triggered()
{
    //停止
    recorder->stop();
}

void MainWindow::on_actionPause_triggered()
{
    //暂停
    recorder->pause();
}

void MainWindow::on_actionQuit_triggered()
{
    this->close();
}

void MainWindow::on_pushButton_file_clicked()
{
    this->openFile();
}
